# 导入必要的库，这些库用于数据处理、数学计算和绘图。
import matplotlib.pyplot as plt  # 用于绘制图表
import numpy as np  # 用于数值计算
import pandas as pd  # 用于数据处理和分析
import math  # 用于数学运算

def tem_curve(data):
    """绘制一天内的温度变化曲线图。

    参数:
        data (DataFrame): 包含'小时'和'温度'两列的数据框。
    """
    hour = list(data['小时'])  # 获取'小时'列的数据并转换成列表
    tem = list(data['温度'])  # 获取'温度'列的数据并转换成列表

    # 处理缺失值：用前一时刻的温度代替。遍历24小时，如果当前温度是NaN，则用上一时刻的温度填充。
    for i in range(0, 24):
        if math.isnan(tem[i]):  # 检查温度是否为NaN
            tem[i] = tem[i - 1]  # 如果是NaN，使用前一个时间点的温度填充

    tem_ave = sum(tem) / 24  # 计算平均温度
    tem_max = max(tem)  # 找到最大温度
    tem_max_hour = hour[tem.index(tem_max)]  # 找到最大温度对应的小时
    tem_min = min(tem)  # 找到最小温度
    tem_min_hour = hour[tem.index(tem_min)]  # 找到最小温度对应的小时

    x = []  # 准备X轴数据，表示24小时
    y = []  # 准备Y轴数据，表示每个小时的温度
    for i in range(0, 24):
        x.append(i)  # 创建X轴，表示24小时
        y.append(tem[hour.index(i)])  # 创建Y轴，表示每个小时的温度

    plt.figure(1)  # 创建一个新的图形窗口
    plt.plot(x, y, color='red', label='温度')  # 绘制温度曲线，标签为'温度'
    plt.scatter(x, y, color='red')  # 在曲线上标记每个时间点的温度
    plt.plot([0, 24], [tem_ave, tem_ave], c='blue', linestyle='--', label='平均温度')  # 绘制平均温度线，虚线样式

    # 标注最高和最低温度，在图表上添加文本标注，显示最高和最低温度的值。
    plt.text(tem_max_hour + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5)  # 标注最大温度
    plt.text(tem_min_hour + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5)  # 标注最小温度

    plt.xticks(x)  # 设置X轴刻度
    plt.legend()  # 显示图例
    plt.title('一天温度变化曲线图')  # 设置图表标题
    plt.xlabel('时间/h')  # 设置X轴标签
    plt.ylabel('摄氏度/℃')  # 设置Y轴标签
    plt.show()  # 显示图表

def hum_curve(data):
    """绘制一天内的相对湿度变化曲线图。

    参数:
        data (DataFrame): 包含'小时'和'相对湿度'两列的数据框。
    """
    # 此函数与tem_curve类似，但针对的是相对湿度数据。
    # 以下省略了与tem_curve相似的代码部分，具体实现可以参考tem_curve函数。

def air_curve(data):
    """绘制一天内的空气质量指数(AQI)变化柱状图。

    参数:
        data (DataFrame): 包含'小时'和'空气质量'两列的数据框。
    """
    hour = list(data['小时'])
    air = list(data['空气质量'])

    # 处理缺失值：用前一时刻的空气质量指数代替。
    for i in range(0, 24):
        if math.isnan(air[i]):
            air[i] = air[i - 1]

    air_ave = sum(air) / 24  # 计算平均空气质量
    air_max = max(air)
    air_max_hour = hour[air.index(air_max)]  # 找到最高空气质量对应的小时
    air_min = min(air)
    air_min_hour = hour[air.index(air_min)]  # 找到最低空气质量对应的小时

    x = []
    y = []
    for i in range(0, 24):
        x.append(i)
        y.append(air[hour.index(i)])

    plt.figure(3)

    # 使用不同颜色绘制不同等级的空气质量柱状图
    for i in range(0, 24):
        if y[i] < 50:
            plt.bar(x[i], y[i], color='lightgreen', width=0.7)  # 1等级
        elif y[i] < 100:
            plt.bar(x[i], y[i], color='wheat', width=0.7)  # 2等级
        elif y[i] < 150:
            plt.bar(x[i], y[i], color='orange', width=0.7)  # 3等级
        elif y[i] < 200:
            plt.bar(x[i], y[i], color='orangered', width=0.7)  # 4等级
        elif y[i] <= 300:
            plt.bar(x[i], y[i], color='darkviolet', width=0.7)  # 5等级
        else:
            plt.bar(x[i], y[i], color='maroon', width=0.7)  # 6等级

    plt.plot([0, 24], [air_ave, air_ave], c='black', linestyle='--')  # 画出平均空气质量虚线
    plt.text(air_max_hour + 0.15, air_max + 0.15, str(air_max), ha='center', va='bottom', fontsize=10.5)  # 标出最高空气质量
    plt.text(air_min_hour + 0.15, air_min + 0.15, str(air_min), ha='center', va='bottom', fontsize=10.5)  # 标出最低空气质量
    plt.xticks(x)
    plt.title('一天空气质量变化曲线图')
    plt.xlabel('时间/h')
    plt.ylabel('空气质量指数AQI')
    plt.show()

def wind_radar(data):
    """绘制一天内的风向雷达图。

    参数:
        data (DataFrame): 包含'风力方向'和'风级'两列的数据框。
    """
    wind = list(data['风力方向'])
    wind_speed = list(data['风级'])

    # 将风力方向转换为角度
    for i in range(0, 24):
        wind[i] = {'北风': 90, '南风': 270, '西风': 180, '东风': 360,
                   '东北风': 45, '西北风': 135, '西南风': 225, '东南风': 315}.get(wind[i], 0)

    degs = np.arange(45, 361, 45)
    temp = []
    for deg in degs:
        speed = []
        # 获取 wind_deg 在指定范围的风速平均值数据
        for i in range(0, 24):
            if wind[i] == deg:
                speed.append(wind_speed[i])
        if len(speed) == 0:
            temp.append(0)
        else:
            temp.append(sum(speed) / len(speed))

    N = 8
    theta = np.arange(0. + np.pi / 8, 2 * np.pi + np.pi / 8, 2 * np.pi / 8)
    radii = np.array(temp)

    # 绘制极区图坐标系
    plt.axes(polar=True)
    colors = [(1 - x / max(temp), 1 - x / max(temp), 0.6) for x in radii]
    plt.bar(theta, radii, width=(2 * np.pi / N), bottom=0.0, color=colors)
    plt.title('一天风级图', x=0.2, fontsize=20)
    plt.show()

def calc_corr(a, b):
    """计算两个变量之间的皮尔逊相关系数。

    参数:
        a (list): 第一个变量的数据列表。
        b (list): 第二个变量的数据列表。

    返回:
        float: 皮尔逊相关系数。
    """
    a_avg = sum(a) / len(a)
    b_avg = sum(b) / len(b)
    cov_ab = sum([(x - a_avg) * (y - b_avg) for x, y in zip(a, b)])
    sq = math.sqrt(sum([(x - a_avg) ** 2 for x in a]) * sum([(x - b_avg) ** 2 for x in b]))
    corr_factor = cov_ab / sq
    return corr_factor

def corr_tem_hum(data):
    """分析温度与相对湿度之间的相关性，并绘制散点图。

    参数:
        data (DataFrame): 包含'温度'和'相对湿度'两列的数据框。
    """
    tem = data['温度']
    hum = data['相对湿度']
    plt.scatter(tem, hum, color='blue')
    plt.title("温湿度相关性分析图")
    plt.xlabel("温度/℃")
    plt.ylabel("相对湿度/%")
    plt.text(20, 40, "相关系数为：" + str(calc_corr(tem, hum)), fontdict={'size': '10', 'color': 'red'})
    plt.show()
    print("相关系数为：" + str(calc_corr(tem, hum)))

def main():
    """主函数，用于加载数据并调用各个分析函数。
    """
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示问题
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
    data1 = pd.read_csv('weather1.csv', encoding='gb2312')  # 读取CSV文件，注意编码方式
    print(data1)  # 打印数据以检查是否正确加载
    tem_curve(data1)  # 调用温度曲线绘制函数
    hum_curve(data1)  # 调用相对湿度曲线绘制函数
    air_curve(data1)  # 调用空气质量指数曲线绘制函数
    wind_radar(data1)  # 调用风向雷达图绘制函数
    corr_tem_hum(data1)  # 调用温湿度相关性分析函数

if __name__ == '__main__':
    main()  # 如果脚本被直接执行，则运行main函数